/**
 * Copyright [2019] [LiBo/Alex of copyright liboware@gmail.com ]
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.dess.base.tools;

import org.reflections.Reflections;
import org.reflections.scanners.*;
import org.reflections.util.ConfigurationBuilder;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * @project-name:dess
 * @package-name:com.hyts.dess.base.tools
 * @author:LiBo/Alex
 * @create-date:2021-08-19 9:54
 * @copyright:libo-alex4java
 * @email:liboware@gmail.com
 * @description:
 *
 * https://www.programcreek.com/java-api-examples/index.php?api=org.reflections.scanners.MethodAnnotationsScanner
 *
 */
public class ReflectionUtils {



    public static Reflections initReflections(String... basePackages){
        Reflections reflections = new Reflections(ConfigurationBuilder.build(basePackages).
                forPackages(basePackages).addScanners(new SubTypesScanner()).addScanners(new MethodAnnotationsScanner())
                .addScanners(new FieldAnnotationsScanner()).addScanners(new MethodParameterScanner()).
                        addScanners(new MethodParameterNamesScanner()));
        return reflections;
    }



    /**
     * 操作机制控制处理方式
     * @param clazz
     * @param basePackages
     * @param <T>
     */
    public static <T> Set<Class<? extends T>> scanSubClassInfoList(Class<T> clazz,String... basePackages){
        // 初始化工具类
        Reflections reflections = ReflectionUtils.initReflections(basePackages);
        // 获取子类
        Set<Class<? extends T>> subTypes = reflections.getSubTypesOf(clazz);
        return subTypes;
    }


    /**
     * 查询扫描所有该注解下的方法集合信息
     * @param annotation
     * @param basePackages
     * @return
     */
    public static  Set<Method> scanMethodInfoListByAnnotation(Class<Annotation> annotation, String... basePackages){
        // 初始化工具类
        Reflections reflections = ReflectionUtils.initReflections(basePackages);
        // 获取子类
        Set<Method> resources =reflections.getMethodsAnnotatedWith(annotation);
        return resources;
    }


    /**
     * 查询扫描所有该注解下的方法集合信息
     * @param annotation
     * @param basePackages
     * @return
     */
    public static  Set<Method> scanMethodInfoListByParamAnnotation(Class<Annotation> annotation, String... basePackages){
        // 初始化工具类
        Reflections reflections = ReflectionUtils.initReflections(basePackages);
        // 获取子类
        Set<Method> pathParamMethods = reflections.getMethodsWithAnyParamAnnotated(annotation);
        return pathParamMethods;
    }


    /**
     * 获取特定参数对应的方法
     * @param paramType
     * @param basePackages
     * @return
     */
    public static Set<Method> scanMethodInfoListByParamType(Class[] paramType, String... basePackages){
        // 初始化工具类
        Reflections reflections = ReflectionUtils.initReflections(basePackages);
        // 获取子类
        Set<Method> pathParamMethods =reflections.getMethodsMatchParams(paramType);
        return pathParamMethods;
    }


    /**
     * 获取特定参数对应的方法
     * @param returnType
     * @param basePackages
     * @return
     */
    public static  Set<Method> scanMethodInfoListByReturnType(Class returnType, String... basePackages){
        // 初始化工具类
        Reflections reflections = ReflectionUtils.initReflections(basePackages);
        // 获取子类
        Set<Method> returnTypeMethod =reflections.getMethodsReturn(returnType);
        return returnTypeMethod;
    }


    /**
     * 查询扫描所有该注解下的字段集合信息
     * @param annotation
     * @param basePackages
     * @param <T>
     * @return
     */
    public static <T> Set<Field> scanFieldInfoListByAnnotation(Class<Annotation> annotation, String... basePackages){
        // 初始化工具类
        Reflections reflections = ReflectionUtils.initReflections(basePackages);
        // 获取子类
        Set<Field> resources =reflections.getFieldsAnnotatedWith(annotation);
        return resources;
    }

    /**
     * 基础包集合信息
     * @param basePackages
     * @return
     */
    public static Set<String> scanResourceFilesByExpression(String expression,String... basePackages){
        // 初始化工具类
        Reflections reflections = ReflectionUtils.initReflections(basePackages);
        Set<String> properties = reflections.getResources(Pattern.compile(expression));
        return properties;
    }

    /**
     *
     * @param args
     */
    public static void main(String[] args){
        // 获取资源文件
        System.out.println(ReflectionUtils.
                scanMethodInfoListByParamType(new Class[]{String.class},"com.hyts.dess.base.thread"));
        System.out.println(ReflectionUtils.
                scanMethodInfoListByReturnType(Void.class,"com.hyts.dess.base.thread"));
    }

}
